import { cloneDeep } from "lodash-es";
import useClipboard from "vue-clipboard3";
import * as XLSX from "xlsx";
import * as xlsx from "xlsx";
import moment from "moment";
const { toClipboard } = useClipboard();

/**
 * 对象复制
 * @param str 复制字符串
 * @returns 复制后的数据
 */
export async function copyLink(str: string) {
  try {
    // 复制
    await toClipboard(str);
    ElMessage.success("复制成功");
    // 复制成功
  } catch (e) {
    // 复制失败
    ElMessage.error("复制失败");
  }
}

/**
 * 粘贴剪切板
 * @param str 复制字符串
 * @returns 复制后的数据
 */
export async function pasteBoard() {
  return navigator.clipboard
    .readText()
    .then((v) => {
      // console.log("获取剪贴板成功：", v, typeof v);
      if (!v) return;
      return v;
    })
    .catch((v) => {
      console.log("获取剪贴板失败: ", v);
      // this.$message.error('获取剪贴板内容失败');
    });
}

/**
 * 对象深克隆
 * @param obj 源对象
 * @returns 克隆后的对象
 */
// 生成指定长度的随机字符串
export function randomString(length: number) {
  // 数字 0123456789
  const NUMBERS = "0123456789";
  // 小写字母 abcdefghijklmnopqrstuvwxyz
  const LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
  // 大写字母 ABCDEFGHIJKLMNOPQRSTUVWXYZ
  const UPPER_CASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  // 常用符号 ~!@#$%^&*()_+
  const SYMBOLS = "~!@#$%^&*()_+";

  // 字符
  const CHARACTERS = NUMBERS + LOWER_CASE_LETTERS + UPPER_CASE_LETTERS; // + SYMBOLS

  let result = "";
  for (let i = 0; i < length; i++) {
    result += CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)];
  }
  return result;
}

// 压缩图片函数，接收一个文件和压缩质量参数
export function compressPic(
  file: any,
  option?: {
    maxWidth?: number;
    maxHeight?: number;
    minSize?: number;
    mimeType?: string;
    quality?: number;
  }
): any {
  const maxWidth = option?.maxWidth || 750; // 最大宽度
  const maxHeight = option?.maxHeight || 750; // 最大高度
  const minSize = option?.minSize ?? 300 * 1024; // 最小压缩文件大小 300kb
  const mimeType = option?.mimeType || "image/jpeg"; // 默认图片类型
  let qualitys: number = option?.quality || 0.8; // 默认压缩阙值0.75
  // 根据文件大小设置不同的默认压缩质量
  if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
    qualitys = 0.85;
  }
  if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
    qualitys = 0.92;
  }

  // 如果上传的是多个文件，递归处理每个文件
  if (file[0]) {
    return Promise.all(
      Array.from(file).map((e: any) => compressPic(e, option))
    );
  } else {
    return new Promise((resolve) => {
      // // 如果图片大小小于300KB，直接返回原始图片数据
      // if (file.size < minSize) {
      //   resolve({
      //     file: file,
      //   });
      // } else {
      // 创建FileReader对象，异步读取存储在客户端上的文件内容
      const reader: FileReader = new FileReader();
      // 读取操作完成时触发该事件，使用格式（必须将接收到的数据从onload发送到其他函数）：reader.onload = e => {}
      reader.onload = ({ target }: ProgressEvent<FileReader>) => {
        // console.log("target----", target);

        //创建img元素
        const image = new Image() as any;
        // 图片加载完成后异步执行，当image的src发生改变，浏览器就会跑去加载这个src里的资源，这个操作是异步的。
        image.onload = async () => {
          // 创建一个新的画布元素和上下文，用于绘制压缩后的图片
          const canvas = document.createElement("canvas");
          const context = canvas.getContext("2d") as any;
          // 计算目标图片的宽度和高度，以适应最大宽度和高度的要求
          let targetWidth = image.width;
          let targetHeight = image.height;

          // 缩放图片尺寸以适应最大宽度和高度
          if (targetWidth > maxWidth || targetHeight > maxHeight) {
            const scaleFactor = Math.min(
              maxWidth / targetWidth,
              maxHeight / targetHeight
            );
            targetWidth *= scaleFactor;
            targetHeight *= scaleFactor;
          }
          // 设置画布的尺寸
          canvas.width = targetWidth;
          canvas.height = targetHeight;
          // 清空画布并在画布上绘制压缩后的图片
          context.clearRect(0, 0, targetWidth, targetHeight);
          context.drawImage(image, 0, 0, targetWidth, targetHeight);
          // 将压缩后的图片数据转换为 data URI。可以使用 type 参数其类型，默认为 PNG 格式。qualitys越小，文件体积越小
          const canvasURL = canvas.toDataURL(mimeType, qualitys);
          // 解码 data URI，获取图片的二进制数据。atob：是ascii to binary，用于将ascii码解析成binary数据，即Base64的解码过程。
          const buffer = atob(canvasURL.split(",")[1]);
          let length = buffer.length;
          //创建一个 Uint8Array 类型的向量，用于存储图片的二进制数据
          const bufferArray = new Uint8Array(new ArrayBuffer(length));
          while (length--) {
            bufferArray[length] = buffer.charCodeAt(length);
          }
          // 创建一个压缩后的文件对象
          const miniFile = new File([bufferArray], file.name, {
            type: mimeType,
          });

          // 解析压缩后的文件对象
          resolve({
            uid: file.uid,
            raw: miniFile,
            origin: file,
            beforeSrc: target?.result,
            afterSrc: canvasURL,
            beforeKB: Number((file.size / 1024).toFixed(2)),
            afterKB: Number((miniFile.size / 1024).toFixed(2)),
          });
        };
        // 设置图片的 src，触发图片加载
        image.src = target?.result;
      };
      // 读取文件内容，并在读取完成后触发 onload 事件
      reader.readAsDataURL(file);
      // }
    });
  }
}

/**
 * 导出列表table数据  导出为Excel表格 .xlxs格式
 * @param data Array类型    table表格数据
 * @param column Array类型    table表格头
 * @param name string类型   文件名称
 * @param type string类型   文件类型中包含日期的,转换为时间格式 + 8H
 */
// 生成指定长度的随机字符串
export function exportTable(
  data: Array<any>,
  column: Array<any>,
  name = "数据列表",
  type = ""
) {
  const dataArr = cloneDeep(data);
  // console.log("数据列表dataArr-----", dataArr);

  const fileds: any = {};
  // 选出我们列表展示的字段key和value值，存放在fileds中
  column.forEach((x) => {
    if (x.prop) {
      fileds[x.prop] = x.label;
    }
  });

  dataArr.forEach((item: any) => {
    for (const i in item) {
      // 当fileds中有这个key时，将item的key替换成 fileds的值（名称）
      // 将item[i]的值赋值给前面的对应的key中，然后在删除原本的item[i]的值
      if (fileds.hasOwnProperty(i)) {
        if (
          type == "moment" &&
          item[i] &&
          (fileds[i] == "日期" ||
            fileds[i] == "支付时间" ||
            fileds[i] == "注册时间" ||
            fileds[i] == "下单时间")
        ) {
          item[fileds[i]] = moment(item[i] + "Z").format("YYYY-MM-DD HH:mm:ss");
          // console.log("item[fileds[i]]+----", fileds[i], item[fileds[i]]);
        } else {
          item[fileds[i]] = item[i] || "";
        }
      }
      delete item[i]; //删除原先的对象属性
    }
  });

  // Create workbook and add the worksheet
  const workbook = XLSX.utils.book_new();

  // Convert JSON data to worksheet
  const worksheet = XLSX.utils.json_to_sheet(dataArr, {
    header: Object.values(fileds),
  });

  XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

  // Convert workbook to binary XLSX data
  const excelData = XLSX.write(workbook, { bookType: "xlsx", type: "array" });

  // Create a Blob from the binary XLSX data
  const blob = new Blob([excelData], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });

  // Save the Blob as a file
  const fileName = `${name}.xlsx`;
  const downloadLink = document.createElement("a");
  downloadLink.href = URL.createObjectURL(blob);
  downloadLink.download = fileName;
  downloadLink.click();
}

// 把文件按照二进制方式读取
function readFile(file: File) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsBinaryString(file);
    reader.onload = (ev) => {
      resolve(ev?.target?.result);
    };
  });
}

/**
 * 将xlsx, xls格式excel文件转为json数据
 * @param {*} file excel文件
 * @param {*} tableHeadCnToEn excel表头文字和字段的对应  示例: { 姓名: 'name', 年龄: 'age'  }
 * @returns
 */
export async function xlsxToJson(file: File, tableHeadCnToEn: any) {
  if (!file) return;
  // 读取file文件的内容(转换为json格式)
  const data = await readFile(file);
  console.log("二进制", data); //解析出的二进制文件
  // type :'binary' 类型为二进制
  let eleData: any = xlsx.read(data, { type: "binary" });
  console.log("eleData", eleData); //解析出的二进制文件
  const eleDataSheet = eleData.Sheets[eleData.SheetNames[0]];
  eleData = xlsx.utils.sheet_to_json(eleDataSheet); // 将解析出的数据转换为json格式（xlsx自带的方法）
  console.log("eleData----****--", eleData);

  const arr: any = [];
  eleData.forEach((item: any) => {
    const userInfo: any = {};
    console.log("item--********------", item, Object.keys(item));

    Object.keys(item).forEach((key) => {
      console.log("key----", key);

      userInfo[tableHeadCnToEn[key]] = item[key];
    });
    arr.push(userInfo);
  });
  return arr;
}
